package com.mapforge.gui.map;

import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.mapforge.listener.TileSelectionEvent;
import com.mapforge.listener.TileSelectionListener;
import com.mapforge.listener.TileStampCreationEvent;
import com.mapforge.listener.TileStampCreationListener;
import com.mapforge.map.TileStamp;

public class TileStampList extends JList implements TileStampCreationListener,
		TileSelectionListener {

	/**
	 * Default serial version ID, here to remove warnings
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * TileStamps this GUI component displays
	 */
	private List<TileStamp> tileStampList;

	/**
	 * Listeners interested in TileStamp selections being performed.
	 */
	private List<TileSelectionListener> tileSelectionListeners;

	private DefaultListModel model;

	public TileStampList() {
		this(null);
	}

	public TileStampList(List<TileStamp> stampList) {
		super();
		model = new DefaultListModel();
		if (stampList != null) {
			this.tileStampList = stampList;
			for (int i = 0; i < tileStampList.size(); i++) {
				model.addElement(tileStampList.get(i));
			}
		} else {
			this.tileStampList = new ArrayList<TileStamp>();
		}
		this.setModel(model);
		this.tileSelectionListeners = new ArrayList<TileSelectionListener>();
		this.setCellRenderer(new TileStampCellRenderer());
		this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		this.addListSelectionListener(new TileStampListSelectionListener());
	}

	public boolean addTileSelectionListener(TileSelectionListener listener) {
		return tileSelectionListeners.add(listener);
	}

	public void clearTileSelectionListeners() {
		this.tileSelectionListeners.clear();
	}

	public boolean removeTileSelectionListener(TileSelectionListener listener) {
		return tileSelectionListeners.remove(listener);
	}

	protected void fireTileSelectionPerformed(TileSelectionEvent event) {
		for (int i = 0; i < tileSelectionListeners.size(); i++) {
			tileSelectionListeners.get(i).tileSelectionPerformed(event);
		}
	}

	private class TileStampListSelectionListener implements
			ListSelectionListener {
		@Override
		public void valueChanged(ListSelectionEvent e) {
			if (!e.getValueIsAdjusting()) {
				Object obj = TileStampList.this.getSelectedValue();
				if (obj != null) {
					TileStamp stamp = (TileStamp) obj;
					System.out.println("TileStampList: "
							+ stamp.getSelection().getBoundingRectangle());
					fireTileSelectionPerformed(new TileSelectionEvent(this,
							stamp.getSelection()));
					repaint();
				}
			}
		}
	}

	/**
	 * If some other component performs a selection event, it will invalidate
	 * this panel's selection.
	 */
	public void tileSelectionPerformed(TileSelectionEvent tileSelectionEvent) {
		this.clearSelection();
		repaint();
	}

	private class TileStampCellRenderer implements ListCellRenderer {
		TileStampLabel label;

		public TileStampCellRenderer() {
			label = new TileStampLabel();
		}

		public Component getListCellRendererComponent(JList list, Object value,
				int index, boolean isSelected, boolean hasFocus) {
			label.setTileStamp((TileStamp) value);
			label.setBackground(isSelected ? Color.BLUE : Color.GRAY);
			return label;
		}

	}

	@Override
	public void tileStampCreationPerformed(TileStampCreationEvent event) {
		this.tileStampList.add(event.getTileStampCreated());
		model.addElement(event.getTileStampCreated());
		validate();
		repaint();
	}
}